/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package io.iec.edp.caf.rpc.remote.grpc;

import io.grpc.Status;
import io.grpc.stub.StreamObserver;
import io.iec.edp.caf.commons.core.SerializerFactory;
import io.iec.edp.caf.commons.core.enums.SerializeType;
import io.iec.edp.caf.commons.utils.SpringBeanUtils;
import io.iec.edp.caf.commons.utils.StringUtils;
import io.iec.edp.caf.core.context.ICAFContextService;
import io.iec.edp.caf.rpc.api.grpc.annotation.GrpcService;
import io.iec.edp.caf.rpc.api.grpc.GrpcInvokeServiceGrpc;
import io.iec.edp.caf.rpc.api.grpc.GrpcResponse;
import io.iec.edp.caf.rpc.api.service.RpcServer;
import io.iec.edp.caf.tenancy.api.context.RequestTenantContextHolder;
import io.iec.edp.caf.tenancy.api.context.RequestTenantContextInfo;
import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

@Slf4j
@GrpcService
public class GrpcServerInvoke extends GrpcInvokeServiceGrpc.GrpcInvokeServiceImplBase {

    private ICAFContextService cafContextService = SpringBeanUtils.getBean(ICAFContextService.class);
    private RpcServer rpcServer = SpringBeanUtils.getBean(RpcServer.class);

    @Override
    public void grpcRemoteInvoke(io.iec.edp.caf.rpc.api.grpc.GrpcRequest request, StreamObserver<io.iec.edp.caf.rpc.api.grpc.GrpcResponse> responseObserver) {
        String serviceId = request.getServiceId();
        LinkedHashMap<String, Object> params = new LinkedHashMap<>();
        params.putAll(request.getParamsMap());
        String context = request.getContext();

        Map<String,String> gspContext = (HashMap<String, String>) SerializerFactory.getDeserializer(SerializeType.Json).deserialize(context, HashMap.class);

        String serviceUnitName = gspContext.get("ServiceUnitName");
        String tenantIdString = gspContext.get("rpc-tenantId");
        Integer tenantId = !StringUtils.isEmpty(tenantIdString) ? Integer.valueOf(tenantIdString) : null;

//        if(gspContext.get("BizContextId")!=null && gspContext.get("BizContextId").length()>0){
//            var bizContext = contextManager.fetch(gspContext.get("BizContextId"));
//            if(bizContext!=null){
//                CAFBizContextHolder.setCurrentContext(bizContext);
//            }
//        }

        //设置租户和su信息
        cafContextService.setCurrentSU(serviceUnitName);
        setTenant(tenantId);

        String result;

        try {
            result = rpcServer.invokeService(serviceId, "", params).toString();
        } catch (Exception e) {
            log.error(e.getMessage(),e);
            responseObserver.onError(Status.INVALID_ARGUMENT.withDescription(e.getMessage()).asException());
            throw new RuntimeException(e);
        } finally {
            restoreTenant(tenantId);
        }


        GrpcResponse resp = GrpcResponse.newBuilder()
                .setMessage(result)
                .build();
        responseObserver.onNext(resp);
        responseObserver.onCompleted();
    }

    /**
     * 设置租户
     *
     * @param tenantId
     */
    private void setTenant(Integer tenantId) {
        if (tenantId != null) {
            RequestTenantContextHolder.set(new RequestTenantContextInfo(tenantId));
        }
    }

    /**
     * 恢复租户上下文
     *
     * @param tenantId
     */
    private void restoreTenant(Integer tenantId) {
        if (tenantId != null) {
            RequestTenantContextHolder.restore();
        }
    }
}
